package org.unt.genlogic;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;

public class Files {

	// private static Logger log = Logger.getLogger("Files");

	public static void writeToFile(String text, String file) {

		FileWriter out;

		try {
			out = new FileWriter(file);
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot instantiate FileWriter, absolute path : " + file, e);
		}

		try {
			out.write(text);
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot write to FileWriter, ", e);
		}

		try {
			out.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot instantiate FileWriter", e);
		}
	}

	public static void writeToFile(List<String> lines, String file) {

		FileWriter out;

		try {
			out = new FileWriter(file);
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot write to FileWriter, ", e);
		}

		try {
			for (String line : lines) {
				out.write(line + "\r\n");
			}
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot write to FileWriter, ", e);
		}

		try {
			out.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot instantiate FileWriter", e);
		}
	}

	public static void writeToFile(List<String> lines, String file, String charset) {

		FileOutputStream fos;
		OutputStreamWriter out;

		// FileWriter out;

		try {

			fos = new FileOutputStream(file);
			out = new OutputStreamWriter(fos, charset);

		} catch (FileNotFoundException e) {
			throw new RuntimeException("FileNotFoundException : cannot find file, absolute path : " + file, e);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("UnsupportedEncodingException : check charset : " + charset, e);
		}

		try {
			for (String line : lines) {
				out.write(line + "\r\n");
			}
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot write to FileWriter, ", e);
		}

		try {
			out.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot instantiate FileWriter", e);
		}
	}

	/**
	 * ANSI is the default code page for my system, for example Windows-1252
	 */
	public static void info() {

		Charset charset = Charset.defaultCharset();
		System.out.println("Default charset : " + charset.displayName() + "\n");

		SortedMap<String, Charset> charsets = Charset.availableCharsets();
		for (String name : charsets.keySet()) {
			System.out.println(name + "\t" + charsets.get(name).displayName());
		}
	}

	/**
	 * IBM037 (EBCDIC), UTF-8, Charset.availableCharsets(); Charset.defaultCharset();
	 */
	public static void writeToFile(String text, String file, String charset) throws IOException {

		FileOutputStream fos = new FileOutputStream(file);
		OutputStreamWriter out = new OutputStreamWriter(fos, charset);

		out.write(text);
		out.close();
	}

	public static List<String> readFileAsList(File file, String charset) {

		InputStreamReader in = null;
		List<String> lines = new ArrayList<String>();

		try {

			FileInputStream fis = new FileInputStream(file);
			in = new InputStreamReader(fis, charset);

		} catch (FileNotFoundException e) {
			throw new RuntimeException("FileNotFoundException : cannot find file, absolute path : " + file, e);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("UnsupportedEncodingException : check charset : " + charset, e);

		}

		BufferedReader br = new BufferedReader(in);
		String line;

		try {
			while ((line = br.readLine()) != null) {
				lines.add(line);
			}
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot read line", e);
		}

		try {
			br.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot close BufferedReader ", e);
		}

		return lines;
	}

	public static String readFileAsString(String fileAbsolutPath, String encoding) {
		File file = new File(fileAbsolutPath, encoding);
		return readFileAsString(file);
	}

	public static String readFileAsString(String fileAbsolutPath) {
		File file = new File(fileAbsolutPath);
		return readFileAsString(file);
	}

	public static String readFileAsString(File file) {

		FileReader reader;

		try {
			reader = new FileReader(file);
		} catch (FileNotFoundException e) {
			throw new RuntimeException("FileNotFoundException : cannot instantiate FileReader", e);
		}

		BufferedReader b = new BufferedReader(reader);

		StringBuffer buf = new StringBuffer();
		String line;

		try {
			while ((line = b.readLine()) != null) {
				buf.append(line + "\n");
			}
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot read line", e);
		}

		try {
			b.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException : cannot close BufferedReader ", e);
		}

		return buf.toString();
	}

	public static List readFileAsList(String fileAbsolutePath, String encoding) throws IOException {
		File file = new File(fileAbsolutePath, encoding);
		return readFileAsList(file);
	}

	public static List readFileAsList(String fileAbsolutePath) throws IOException {
		File file = new File(fileAbsolutePath);
		return readFileAsList(file);
	}

	public static List readFileAsList(File file) throws IOException {

		FileReader reader = new FileReader(file);
		BufferedReader b = new BufferedReader(reader);

		List list = new ArrayList();

		String line;
		while ((line = b.readLine()) != null) {
			list.add(line.trim());
		}
		b.close();

		return list;
	}

	public static void listFilesRecursively(File dir, List<File> filesList) {

		File[] files = dir.listFiles();

		if (files == null)
			return;

		for (int i = 0; i < files.length; i++) {

			if (files[i].isDirectory()) {
				// System.out.println("Dir " + files[i].getAbsolutePath() + " ...");
				listFilesRecursively(files[i], filesList);
			} else {
				filesList.add(files[i]);
			}
		}
	}

	public static void listFilesRecursively(File dir, List<File> filesList, Set<String> extensions) {

		File[] files = dir.listFiles();

		for (int i = 0; i < files.length; i++) {

			String name = files[i].getName();

			if (files[i].isDirectory()) {

				listFilesRecursively(files[i], filesList, extensions);

			} else {

				if (extensions != null && extensions.contains(name.substring(name.lastIndexOf(".") + 1))) {
					filesList.add(files[i]);
				}
			}
		}
	}

	public static void listFilesRecursively(File dir, List filesList, Set bannedFiles, Set bannedExtensions, Set bannedDirs) {

		File[] files = dir.listFiles();

		for (int i = 0; i < files.length; i++) {

			String name = files[i].getName();

			if (files[i].isDirectory()) {

				if (bannedDirs != null && bannedDirs.contains(name) || bannedFiles != null && bannedFiles.contains(name)) {
					continue;
				}

				listFilesRecursively(files[i], filesList, bannedFiles, bannedExtensions, bannedDirs);

			} else {

				if (bannedExtensions != null && bannedExtensions.contains(name.substring(name.lastIndexOf(".") + 1))) {
					continue;
				}

				filesList.add(files[i]);
			}
		}
	}
}
